/**
 * 
 */
package io;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;

import game.Building;
import game.Game;
import game.Map;
import game.Player;
import game.Unit;

/**
 * @author Remi REBILLARD
 *
 */
public class ImportGame {
	
	private BufferedReader buffer;
	private String[] tmpStr;
	
	//GAME
	private String game_header_version;
	private String game_map_name;
	private Integer game_header_data;
	
	//PLAYER
	private Integer[] player_header;
	private ArrayList< Player > players;
	
	//MAP
	private Integer[] map_header;
	private Map map;
	private HashSet< Unit > units;
	private HashSet< Building > buildings;
	
	/**
	 * @param is
	 */
	public ImportGame( BufferedReader is ){
		this.buffer = is;
		this.player_header = new Integer[2];
		this.players = new ArrayList< Player >();
		this.map_header = new Integer[4];
	}
	
	/**
	 * @param game
	 * @throws IOException
	 */
	public void read( Game game ) throws IOException{
		
	//GAME_HEADER
		game_header_version = buffer.readLine();					//VERSION
		if( !game_header_version.equals( "game_file_map\t1" ) )
			throw new IOException( "Invalid Header of Game" );
		game_map_name = buffer.readLine();							//MAP_NAME
		game_header_data = Integer.parseInt( buffer.readLine() );	//START_TURN
		
		try{
			loadImport( game );
			loadPlayer( game );
			loadMap( game );
		} catch(IOException e){
			throw new IOException( e );
		}
		
	//GAME_CONTENT
		game.setName( game_map_name );
		game.setMap( map );
		map.setBuildings(buildings);
		map.setUnits(units);
		game.setPlayers( players );
		game.setTurn( game_header_data );
		game.setPlayerTurn( player_header[1] );	
	}
	
	/**
	 * @param game
	 * @throws IOException
	 */
	private void loadImport( Game game ) throws IOException{
		try{
			game.setBuildingTypes( ( new ImportBuildingType( new FileInputStream( "data/database/building.tsv" ) ) ).read() );
			//game.setTableDamage( ( new ImportTableDamage( new FileInputStream( "data/database/damage.tsv" ) ) ).read() );
			//game.setTableMovementCost( ( new ImportTableMovement( new FileInputStream( "data/database/movement.tsv" ) ) ).read() );
			game.setTileTypes( ( new ImportTileType( new FileInputStream( "data/database/tile.tsv" ) ) ).read() );
			game.setUnitTypes( ( new ImportUnitType( new FileInputStream( "data/database/unit.tsv" ) ) ).read() );
		} catch( Exception e ) {
			throw new IOException( "Error to load the Import in ImportGame" );
		}
	}
	
	/**
	 * @param game
	 * @throws IOException
	 */
	private void loadPlayer( Game game ) throws IOException{
		
		try {
			tmpStr = buffer.readLine().split( "\t" );
			player_header[0] = Integer.parseInt( tmpStr[0] );	//NB_PLAYERS
			player_header[1] = Integer.parseInt( tmpStr[1] );	//PLAYER_TURN
			
			for(int i = 0; i < player_header[0]; i++){
				tmpStr = buffer.readLine().split( "\t" );
				Player tmpPlayer = new Player( Integer.parseInt( tmpStr[0] ), tmpStr[1] );	//JOUEURS
				tmpPlayer.setHasLost( Boolean.parseBoolean( tmpStr[2] ) );
				players.add( tmpPlayer );
			}
		} catch (Exception e) {
			throw new IOException( "Error to load Players in ImportGame" );
		}
	}
	
	/**
	 * @param game
	 * @throws IOException
	 */
	private void loadMap( Game game ) throws IOException{
		try {
			tmpStr = buffer.readLine().split( "\t" );
			map_header[0] = Integer.parseInt( tmpStr[0] );	//MAP_WIDTH
			map_header[1] = Integer.parseInt( tmpStr[1] );	//MAP_HEIGHT
			map_header[2] = Integer.parseInt( tmpStr[2] );	//NB_BUILDINGS
			map_header[3] = Integer.parseInt( tmpStr[3] );	//NB_UNITS
			map = new Map( map_header[0].intValue() , map_header[1].intValue() );	//MAP
			
			//TILES
			for(int j = 0; j < map_header[1]; j++){
				tmpStr = buffer.readLine().split( "\t" );
				for(int i = 0; i < map_header[0]; i++){
					map.setTile( i, j, Integer.parseInt( tmpStr[i] ) );
				}
			}
			this.buildings = new HashSet<Building>();
			//BUILDINGS
			for(int i = 0; i < map_header[2]; i++){ 
				tmpStr = buffer.readLine().split( "\t" );
				Building tmpBuilding = new Building( game.getBuildingTypes().get( tmpStr[0] ), Integer.parseInt( tmpStr[2] ), Integer.parseInt( tmpStr[3] ) );
				tmpBuilding.setPlayer( players.get( Integer.parseInt( tmpStr[1] ) ) );	//PLAYER
				buildings.add( tmpBuilding );
			}

			this.units = new HashSet<Unit>();
			//UNITS
			for(int i = 0; i < map_header[3]; i++){	
				tmpStr = buffer.readLine().split( "\t" );
				Unit tmpUnit = new Unit( game.getUnitTypes().get( tmpStr[0] ), players.get( Integer.parseInt( tmpStr[1] ) ), Integer.parseInt( tmpStr[2] ), Integer.parseInt( tmpStr[3] ) );
				tmpUnit.setHealth( Integer.parseInt( tmpStr[4] ) );			//HEALTH
				tmpUnit.setActive( Boolean.parseBoolean( tmpStr[5] ) );		//IS_ACTIVE
				units.add( tmpUnit );
			}
			
		} catch (Exception e) {
			throw new IOException("Error loading map");
		}
	}
	
}
